home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 002 / tabs21.arc / TABS21.ASM next >
Assembly Source File  |  1986-10-14  |  16KB  |  727 lines

  1.     Page    74,132
  2.     Title    TABS - Align ASCII File
  3.  
  4.     Comment    | Version 2.1, Oct 14, 1986
  5.  
  6. TABS Command
  7. -----------------
  8.  
  9. Purpose:   Replace blanks with TAB character(s); or expand TABs.
  10.  
  11. Format:       TABS     [d:[input.ext]] [d:[output.ext]] [/D]
  12.  
  13. Remarks:   Any TAB characters found are    first expanded.    If TABS
  14.     appear within quoted strings - out of context -    they will
  15.     not be expanded.
  16.  
  17.     The /D option may be used to remove TABs from a    file,
  18.  
  19.     The maximum logical record size    is 255,    see MAXREC equate.
  20.     Defacto    tab columns are    9,17,25,...
  21.  
  22.     Written    by Vernon Buerg    for the    IBM PC using DOS 2.
  23.     For public domain use.
  24.  
  25. Notes:    Version    1.6 includes a correction for the use of wildcards
  26.     to name    the output file    the same as the    input file if only
  27.     a drive    was supplied for the output file name.
  28.  
  29.     Version    1.7 fixes a problem regarding the EOF character. It
  30.     now considers the EOF as the end of a file and will no longer
  31.     copy data after    that point. Also, if wildcards are used, all
  32.     matching files are processed.
  33.  
  34.     Version    1.8 cleans up the messages displayed.
  35.  
  36.     Version 1.9 requires the ouput file on a different drive,
  37.     or in a different path.
  38.  
  39.     Version 2.0 improves performance, adds EOF to end of file.
  40.     Version 2.1 ignore EOF (1Ah ) in input files.
  41.  
  42. -----------------                    |
  43.  
  44. CSeg    Segment    Public Para 'CODE'
  45.     Assume    CS:Cseg,DS:Cseg,ES:CSeg
  46.     Org    100h
  47.  
  48. Tabs    Proc    Far
  49.     Mov    CS:Stk_Top,SP        ;Save stack ptr    to insure return
  50.  
  51.     Call    ChkVer            ;Check for DOS 2
  52.  
  53.     Call    Alloc            ;Get maximum I/O buffers
  54.  
  55.     Call    GetFile            ;Get file names
  56.  
  57. Again:
  58.     Call    OpenIn            ;Open input
  59.  
  60.     Call    OpenOut            ; and output
  61.  
  62.     Call    Inform            ;Display "cooking" message
  63.  
  64.     Call    GenTab            ;Generate tabs
  65.  
  66.     Call    Flush            ;Empty the output buffer
  67.  
  68.     Call    Close            ;Close files
  69.  
  70.     Call    Next            ;Get next matching file
  71.     Or    AL,AL
  72.     Jz    Again
  73.     Sub    AL,AL            ;All done
  74.     Jmp    Short Exit
  75.  
  76.  
  77. Error:    Mov    SP,Stk_Top        ;Insure    proper return
  78.     Call    PrintS            ;Print any message
  79.  
  80.     Mov    AL,1            ;Set ERRORLEVEL    to 1
  81. Exit:    Mov    AH,4Ch
  82.     Int    21h            ;Return    to DOS
  83.     Page
  84. ;
  85. ;    Constants, equates, and    work areas
  86.  
  87. BufLen    Dw    0            ;I/O buffer size
  88. MinCore    Equ    512            ;Minimum of one    sector
  89. Maxrec    Equ    255            ;Longest logical record
  90.  
  91. S_Quote    Equ    34            ;Single    quote
  92. D_Quote    Equ    39            ;Double    quote
  93. Tab    Equ    9
  94. LF    Equ    10
  95. CR    Equ    13
  96. EOF    Equ    1Ah
  97. Stopper    Equ    255
  98.  
  99. Sw    Db    0            ;Number    of blanks skipped
  100. Qsw    Db    0            ;Quote switch
  101. Detab    Db    0            ;Non-zero for detab function
  102. Stk_Top    Dw    0            ;SP at entry
  103.  
  104. Msg1    Db    CR,LF,'Input failed to open, '
  105. Input    Db    76 Dup (0),0,Stopper    ;Drive:path\name.ext
  106. IHandle    Dw    0            ;Input file handle
  107. Ilen    Dw    0            ;Input block length
  108. Iptr    Dw    0            ;Offset    to next    char
  109. In_Ptr    Dw    0            ;Seg offset
  110.  
  111. Msg2    Db    CR,LF,'Output failed to open, '
  112. Output    Db    76 Dup (0),0,CR,LF,Stopper
  113. OHandle    Dw    0            ;Output    file handle
  114. Olen    Dw    0            ;Bytes in output buffer
  115. Optr    Dw    0            ;Offset    to next    char
  116. Out_Ptr    Dw    0            ;Seg offset
  117.  
  118. Spaces    Db    8 Dup (' ')
  119. FilePtr    Dw    Offset Input        ;Addr of file name part
  120. NewPtr    Dw    Offset Output        ;Spot for output file name
  121. DTA    Db    48 Dup (0)        ;DOS data transfer area
  122.     Page
  123. ;
  124. ;    Messages
  125.  
  126. Version    Db    'TABS - Version 2.1 - V.Buerg',CR,LF,CR,LF
  127.     Db    'Usage:  TABS  infile  outfile  [/D]',CR,LF
  128.     Db    ' o  infile and outfile may include drive and path names',CR,LF
  129.     Db    ' o  use ending /D to expand tabs to spaces.',CR,LF
  130.     Db    ' o  Oct 14, 1986; public domain.',Stopper
  131.  
  132. Sorry    Db    CR,LF,'Wrong PC DOS Version',Stopper
  133. Msg3f    Db    CR,LF,'Read error',Stopper
  134. Msg40    Db    CR,LF,'Write error or Disk full.',Stopper
  135. Msg4a    Db    CR,LF,'Not enough memory',Stopper
  136. Msg4e    Db    CR,LF,'No matching file(s) found',Stopper
  137. InformD    Db    'de-'
  138. Cooking    Db    'TABS:',9,Stopper
  139. Mark    Db    9,'-> ',Stopper
  140. NewLine    Db    CR,LF,Stopper
  141.  
  142. Code2    Db    'File not found ',Stopper
  143. Code3    Db    'Path not found ',Stopper
  144. Code4    Db    'Too many files ',Stopper
  145. Code5    Db    'Access denied  ',Stopper
  146.     Page
  147. ;
  148. ;    Replace    blanks with tabs
  149.  
  150. GenTab    Proc    Near
  151. Loop:    Call    GetRec            ; Get a record, length in CX
  152.     Jnc    Init_Rec        ; Was it end of file?
  153.     Jmp    Done
  154. Init_Rec:
  155.     Sub    BX,BX            ;Output    column
  156.     Mov    Sw,BL            ;No blanks yet
  157.     Mov    Qsw,BL            ;No quotes yet
  158.     Or    CX,CX            ;Any data in record?
  159.     Jz    Null            ; no, just CR-LF
  160.  
  161. Set1:    Mov    SI,Offset Rec        ;Look for blanks and
  162. Wloop:    Lodsb                ; replace strings of blanks
  163.     Inc    BX            ; with tab characters
  164.     Cmp    AL,D_Quote        ;Don't count blanks
  165.     Je    Chk2d            ; within single    or double
  166.  
  167. Chk1:    Cmp    AL,S_Quote        ;Insert    TABs for any
  168.     Je    Chk3d            ; blanks skipped before
  169.  
  170. Chk3:    Cmp    Detab,0            ;Leave expanded    record as-is
  171.     Jne    Check            ; if de-tabbing
  172.     Cmp    AL,' '            ;Tis a blank?
  173.     Jne    Check            ; no, see if eof
  174.     Test    Qsw,3            ;Within    quotes?
  175.     Jnz    Check
  176.     Inc    Sw
  177.     Test    BL,07h            ;Ready for a tab?
  178.     Jnz    Tloop            ; no, keep going
  179.     Mov    AL,Tab            ; yes, send one
  180.     Jmp    Copy
  181. Chk3d:
  182.     Xor    Qsw,1            ; a quote
  183. Chk2:    Cmp    Sw,0            ;Must re-insert
  184.     Je    Check            ; any blanks skipped
  185.     Jmp    Insert            ; if not enough    for a TAB
  186. Chk2d:
  187.     Xor    Qsw,2            ; quoted strings
  188.     Jmp    Chk2
  189.  
  190. Check:     Cmp    Detab,0
  191.     Jne    Copy
  192.     Test    Qsw,3            ;When a    non-blank is
  193.     Jnz    Copy            ; encountered, insert a    TAB
  194.     Cmp    Sw,0            ; if there were    blanks
  195.     Je    Copy            ; before it
  196.     Mov    DX,BX
  197.     Dec    DL
  198.     Test    DL,07h            ;If the    non-blank is not
  199.     Jnz    Insert            ; in a TAB column, then
  200.     Push    AX            ; keeps    all the    blanks
  201.     Mov    AL,Tab
  202.     Call    PutChar
  203.     Pop    AX
  204. Copy:    Call    PutChar            ; and write it
  205.     Mov    Sw,0            ;Ind not blank
  206.  
  207. Tloop:    Loop    Wloop
  208.  
  209. Null:    Mov    AL,CR            ;Append    CR
  210.     Call    PutChar
  211.     Mov    AL,LF            ; and LF
  212.     Call    PutChar
  213.     Jmp    Loop
  214.  
  215. Insert:    Push    AX            ;Insert    any blanks that
  216.     Mov    DL,Sw            ; didn't line up on
  217. Blanks:    Cmp    DL,1            ; a TAB    column
  218.     Jb    None
  219.     Mov    AL,' '
  220.     Call    PutChar
  221.     Dec    DL            ;Decr insert count
  222.     Jmp    Blanks            ; and continue
  223. None:    Pop    AX            ;Get char back
  224.     Jmp    Copy
  225.  
  226. Done:    Ret
  227. GenTab    Endp
  228.     Page
  229. ;
  230. ;    Build a    logical    record with TABs expanded
  231.  
  232. GetRec    Proc    Near
  233.     Sub    DI,DI            ;Target    record offset
  234.     Mov    Qsw,0            ;Quote indicator
  235.  
  236. Get1:    Call    GetChar            ; Build up a logical record
  237.     Jc    GetEof             ; End of file?
  238.     Cmp    AL,CR            ; Looking for a CR or LF
  239.     Je    Get1            ;  as end-of-record
  240.     Cmp    AL,LF
  241.     Je    Get7
  242.     Cmp    AL,EOF            ; Ignore EOF control char
  243.     Jne    Get1e
  244.     Mov    AL,' '
  245. Get1e:    Cmp    AL,S_Quote        ; Don't expand tabs
  246.     Jne    Get2            ;  found within a
  247.     Xor    Qsw,1            ;  quoted string
  248. Get2:    Cmp    AL,D_Quote
  249.     Jne    Get3
  250.     Xor    Qsw,2
  251. Get3:    Cmp    AL,Tab            ;Is it TAB?
  252.     Jne    Get5            ; no, pass it
  253.     Test    Qsw,3            ;Within    quotes?
  254.     Jnz    Get5            ; yes, pass it as-is
  255. Get4:    Mov    Rec[DI],' '        ;Expand    embedded tabs
  256.     Inc    DI            ; with blanks
  257.     Test    DI,0007h
  258.     Jz    Get1
  259.     Jmp    Get4
  260.  
  261. Get5:    Mov    Rec[DI],AL        ;Build the record by
  262.     Inc    DI            ; copying each character
  263.     Cmp    DI,Maxrec        ; or TABs expanded to blanks
  264.     Jae    Get6
  265.     Jmp    Get1            ; no, continue
  266. Get6:    Clc
  267. GetEof:    Mov    CX,DI            ;Final record length
  268.     Ret
  269.  
  270. Get7:    Cmp    Rec-1[DI],' '        ;Omit trailing blanks
  271.     Jne    Get6
  272.     Dec    DI
  273.     Jz    Get6
  274.     Jmp    Get7
  275.  
  276. GetRec    Endp
  277.     Page
  278. ;
  279. ;    Extract    one char from record
  280.  
  281. GetChar    Proc    Near            ;Read char into    AL
  282. Read1:    Cmp    Ilen,0            ;Any in    buffer?
  283.     Je    Read            ; no, read next    block
  284.     Mov    SI,Iptr            ; yes, get offset in buf
  285.     Lodsb
  286.     Mov    Iptr,SI            ;Offset    for next one
  287.     Dec    Ilen
  288.     Clc
  289.     Ret
  290.  
  291. Read:    Push    CX
  292.     Mov    BX,IHandle        ;Read a    block of data
  293.     Mov    CX,BufLen        ; into Input (segment) buffer
  294.     Mov    DX,In_Ptr
  295.     Mov    Iptr,DX
  296.     Mov    AH,3Fh
  297.     Int    21h
  298.     Pop    CX
  299.     Mov    Ilen,AX            ; and length
  300.     Jc    Read3
  301.     Or    AX,AX            ; Anything read?
  302.     Jnz    Read1            ;  yes, pick it up
  303.     Stc                ;  no, return EOF
  304.     Ret
  305.  
  306. Read3:    Mov    DX,Offset Msg3f        ;Say I/O ERROR
  307.     Jmp    Error
  308. GetChar    Endp
  309.     Page
  310. ;
  311. ;    Block output records
  312.  
  313. PutChar    Proc    Near               ;Write from AL
  314.     Mov    DI,Optr            ;Offset    in buffer
  315.     Stosb
  316.     Mov    Optr,DI            ;New buffer ptr
  317.     Dec    Olen            ;Full buffer?
  318.     Jz    PutChars
  319.     Ret
  320. PutChars:
  321.     Call    Write            ;  yes, write it
  322.        Ret
  323. PutChar    Endp
  324.  
  325.  
  326. Write    Proc    Near
  327.     Push    CX            ;Write full buffer
  328.     Mov    CX,BufLen        ;Buffer size
  329.  
  330. Write3:    Push    AX
  331.     Push    BP
  332.     Push    BX
  333.     Push    DX
  334.     Mov    BX,OHandle        ;Get file handle
  335.     Mov    BP,CX            ;Save size requested
  336.     Mov    DX,Out_Ptr
  337.     Mov    Optr,DX
  338.     Mov    AX,BufLen        ;Reset buffer size free
  339.     Mov    Olen,AX
  340.     Mov    AH,40h            ;Write the block
  341.     Int    21h
  342.     Jc    Writer            ;Write OK?
  343.     Sub    BP,AX            ;Wrote all data?
  344.     Jz    Write2            ; yes, good
  345. Writer:    Mov    DX,Offset Msg40        ; no, say I/O error
  346.     Jmp    Error
  347.  
  348. Flush:    Mov    AL,EOF            ;Append EOF for funny programs
  349.     Call    PutChar
  350.     Push    CX            ;Write data left over
  351.     Mov    CX,BufLen
  352.     Sub    CX,Olen            ;Any left in output?
  353.     Jnz    Write3
  354.     Pop    CX
  355.     Ret
  356.  
  357. Write2:    Pop    DX
  358.     Pop    BX
  359.     Pop    BP
  360.     Pop    AX
  361.     Pop    CX
  362.     Ret
  363. Write    Endp
  364.     Page
  365.  
  366. ;    Open input file
  367.  
  368. OpenIn    Proc    Near
  369.     Mov    DX,Offset Input
  370.     Mov    AX,3D00h        ;For input
  371.     Int    21h
  372.     Jnc    Openi
  373.     Mov    DX,Offset Msg1
  374.     Jmp    OpenErr
  375.  
  376. Openi:    Mov    IHandle,AX
  377.     Ret
  378. OpenIn    Endp
  379.  
  380. ;    Open output file
  381.  
  382. OpenOut    Proc    Near
  383.     Mov    DX,Offset Output
  384.     Sub    CX,CX            ;Normal    file attribute
  385.     Mov    AH,3Ch            ;Create    a file
  386.     Int    21h
  387.     Jnc    Openo
  388.     Mov    DX,Offset Msg2        ;Oops, can't open output
  389.     Jmp    OpenErr
  390.  
  391. Openo:    Mov    OHandle,AX
  392.     Ret
  393. OpenOut    Endp
  394.  
  395. ;    Determine why OPEN failed
  396.  
  397. OpenErr:Cmp    AL,2            ;AL has    reason code
  398.     Jb    Opene
  399.     Cmp    AL,5
  400.     Ja    Opene
  401.     Sub    BX,BX            ;Get offset to reason
  402.     Mov    BL,AL            ; text for open    failure
  403.     Mov    CL,4
  404.     Shl    BX,CL
  405.     Call    PrintS            ;Say OPEN FAILED
  406.     Mov    DX,Offset NewLine
  407.     Call    PrintS
  408.     Lea    DX,Code2-32[BX]
  409. Opene:    Jmp    Error
  410.  
  411. ;    Close input/output
  412.  
  413. Close    Proc    Near            ;Close files
  414.     Mov    BX,OHandle        ; output
  415.     Mov    AH,3Eh
  416.     Int    21h
  417.  
  418.     Mov    BX,IHandle        ; input
  419.     Mov    AH,3Eh
  420.     Int    21h
  421.     Ret
  422. Close    Endp
  423.     Page
  424. ;
  425. ;    Get file names from command line
  426.  
  427. GetFile    Proc    Near            ;Get file name(s)
  428.     Mov    SI,80h            ;Point to command line
  429.     Sub    CX,CX            ;The PSP may contain one or two
  430.     Or    CL,Byte    Ptr DS:[SI]    ; filenames separated by blanks
  431.     Jnz    GetF0
  432. GetUse:    Mov    DX,Offset Version    ;None, display usage message
  433.     Jmp    Error
  434.  
  435. GetF0:    Mov    DI,Offset Input        ;Target    is infile for
  436.     Inc    SI            ; first    command    operand
  437.  
  438. GetF1:    Lodsb                ;Copy command line to file names
  439.     Cmp    AL,' '            ; by skipping leading blanks
  440.     Jne    GetF1a            ; until    a CR is    found
  441.     Loope    GetF1
  442.     JCXz    GetUse            ;If all    blank
  443.  
  444. GetF1a:    Cmp    AL,CR            ;Is it CR, end of line?
  445.     Je    GetF5            ; yes, terminate infile    name
  446.     Cmp    AL,'/'            ;Or option string?
  447.     Je    GetF1c
  448.     Cmp    AL,' '            ;Ending    blank?
  449.     Je    GetF2
  450.     Stosb
  451.     Lodsb
  452.     Loop    GetF1a
  453.     Jmp    GetF5
  454.  
  455. GetF1c:    Mov    AX,0FF00h        ;Terminate fname operand
  456.     Stosw
  457.     Lodsb                ;Get option letter
  458.     Cmp    AL,'D'            ;Set /D    option for detabbing
  459.     Je    GetF1d
  460.     Cmp    AL,'d'
  461.     Jne    GetF3
  462. GetF1d:    Mov    Detab,Stopper
  463. GetF3:
  464.     Jmp    GetF6
  465.  
  466. GetF2:    Mov    AX,0FF00h        ;Terminate fname operand
  467.     Stosw
  468.     Lea    DI,ES:Output        ;Process second    fname
  469. GetF2a:    Lodsb
  470.     Cmp    AL,' '            ;Skip intervening blanks
  471.     Jne    GetF2b
  472.     Loope    GetF2a
  473.     JCXz    GetF6            ;If no operand
  474.  
  475. GetF2b:    Cmp    AL,CR            ;Is it CR, end of line?
  476.     Je    GetF5            ; yes, end of name
  477.     Cmp    AL,'/'            ;Or option string?
  478.     Je    GetF1c            ; yes, copy it
  479.     Cmp    AL,' '            ;Or ending blank?
  480.     Je    GetF2c
  481.     Stosb                ;Copy second operand
  482.     Mov    NewPtr,DI
  483. GetF2c:    Lodsb
  484.     Loop    GetF2b
  485.  
  486. GetF5:    Mov    AX,0FF00h        ;Append    zero and dollar    sign
  487.     Stosw
  488.  
  489. GetF6:
  490. GetF7:    Cmp    Input,0            ;Any input name?
  491.     Jne    GetF8            ; yes, try output name
  492.     Jmp    GetUse            ; no, display usage
  493.  
  494. GetF8:
  495.     Call    Find            ;Find first matching file
  496. GetF8a:    Cmp    Output,0        ;Any output name?
  497.     Jne    GetF9            ; yes, further check name
  498.     Cmp    Input+1,':'        ;Make sure don't over-write
  499.     Je    GetFo            ; the input file
  500.     Jmp    GetUse
  501.  
  502. GetF9:    Cmp    Word Ptr OutPut+1,003Ah    ;If just a drive is given
  503.     Jne    GetFp            ; for the output
  504.     Mov    DI,Offset OutPut+2    ;Skip over drive
  505.     Mov    Newptr,DI
  506.     Jmp    Short GetFo        ; and copy as outfile name
  507.  
  508. GetFp:    Cmp    Word Ptr Output+1,'\:'    ;Drive and path?
  509.     Je    GetFs            ; yes, append infile name
  510.     Cmp    Byte Ptr Output,'\'    ;Just a    path?
  511.     Jne    GetFend            ; no, outfile is a filename
  512.  
  513. GetFs:    Mov    DI,NewPtr        ;Append    path delimiter
  514.     Mov    AL,'\'
  515.     Stosb
  516.     Mov    NewPtr,DI
  517. GetFo:    Mov    CX,74            ;Copy the input    filename
  518.     Mov    DI,NewPtr        ; after    the outfile spec
  519.     Mov    SI,FilePtr
  520.     Rep    Movsb
  521. GetFend:Ret
  522. GetFile    Endp
  523.     Page
  524. ;
  525. ;    Find first matching file, just cuz I'm lazy
  526.  
  527. Find    Proc    Near            ;Find first matching file
  528.     Mov    DX,Offset DTA        ;Set data xfer area
  529.     Mov    AH,1Ah
  530.     Int    21h
  531.     Mov    DX,Offset Input        ;Input path\filename.ext
  532.     Sub    CX,CX            ;Search    for first normal file
  533.     Mov    AH,4Eh
  534.     Int    21h
  535.     Jnc    Find1
  536. Find0:    Mov    DX,Offset Msg4e        ;Say NO    MATCHING FILE
  537.     Jmp    Error
  538.  
  539. Find1:    Or    AL,AL            ;Set ZF    for return
  540.     Jnz    Find0            ; if none found
  541.     Mov    DI,Offset Input
  542.     Cmp    Byte Ptr [DI+1],':'    ;If drive was supplied
  543.     Jne    Find2            ; leave    it in file name
  544.     Add    DI,2
  545. Find2:    Cmp    Byte Ptr [DI],'\'    ;If path was supplied
  546.     Jne    Find4a            ; try to leave it in Input name
  547.     Mov    SI,Offset Input+75
  548.     Std
  549.     Mov    CX,76
  550. Find3:    Lodsb
  551.     Cmp    AL,'\'            ;Find the last separator
  552.     Je    Find4            ; which    is the filename    spec
  553.     Loop    Find3
  554.     Mov    SI,DI
  555.  
  556. Find4:    Mov    DI,SI
  557.     Add    DI,2
  558. Find4a:    Mov    FilePtr,DI        ;Save addr of filename part
  559. Find5:    Mov    CX,13            ;Copy found name to Input name
  560.     Mov    DI,FilePtr
  561.     Cld
  562.     Mov    SI,Offset DTA+30    ; after    drive and first    path name
  563. Find7:    Lodsb
  564.     Stosb
  565.     Cmp    AL,0            ;Don't want crud in message
  566.     Loopne    Find7
  567. Find9:    Mov    AL,Stopper
  568.     Stosb
  569.     Sub    AL,AL            ;Set good return code
  570.     Ret
  571.  
  572. Next:    Mov    AH,4Fh            ;Get next matching file
  573.     Int    21h
  574.     Or    AL,AL            ; any more?
  575.     Jnz    Nexted            ; no, just return
  576.  
  577.     Mov    Qsw,0            ;Re-initialize
  578.     Mov    Sw,0
  579.     Mov    AX,BufLen
  580.     Mov    Olen,AX            ;Reset buffer counts
  581.     Mov    Ilen,0
  582.     Mov    AX,Out_Ptr        ;Reset buffer ptrs
  583.     Mov    Optr,AX
  584.     Mov    AX,In_Ptr
  585.     Mov    Iptr,AX
  586.     Mov    AX,Offset Output    ;Was output name supplied?
  587.     Cmp    AX,Newptr
  588.     Jne     Next1
  589.     Mov    Output,0        ;Reset output file name
  590. Next1:
  591.     Mov    CX,8            ;Clear message prefix
  592.     Mov    SI,Offset Spaces
  593.     Mov    DI,Offset InformD
  594.     Rep    Movsb
  595.     Mov    Cooking,CR
  596.     Mov    Cooking+1,LF
  597.  
  598.     Mov    DI,NewPtr        ;Copy input name as output name
  599.     Mov    CX,13
  600.     Mov    SI,Offset DTA+30
  601. Next7:    Lodsb
  602.     Stosb
  603.     Cmp    AL,0            ;Don't want crud in message
  604.     Loopne    Next7
  605.     Mov    AL,Stopper
  606.     Stosb
  607.     Jmp    Find5            ; yes, copy the    name
  608. Nexted:    Ret
  609. Find    Endp
  610.  
  611.     Page
  612. ;
  613. ;    Display    "cooking" message
  614.  
  615. Inform    Proc    Near
  616.     Mov    DX,Offset Cooking
  617.     Cmp    Detab,0
  618.     Je    Inform1
  619.     Mov    DX,Offset InformD
  620. Inform1:Call    PrintS
  621.     Mov    DX,Offset Input
  622.     Call    PrintS
  623.     Mov    DX,Offset Mark
  624.     Call    PrintS
  625.     Mov    DX,Offset Output
  626.     Call    PrintS
  627.     Ret
  628. Inform    Endp
  629.  
  630. ChkVer    Proc    Near
  631.     Mov    AH,30h
  632.     Int    21h            ;Verify    DOS 2.0    or later
  633.     Cmp    AL,2
  634.     Jae    Chk9
  635.     Mov    DX,Offset Sorry
  636.     Jmp    Error
  637. Chk9:    Ret
  638. ChkVer    Endp
  639.  
  640. PrintS    Proc    Near            ;Print string like Int 21h (9)
  641.     Push    BX            ;DX points to string
  642.     Push    SI
  643.     Mov    SI,DX
  644. PS1:    Lodsb
  645.     Cmp    AL,Stopper        ;String    ends in    a hex FF
  646.     Je    PS9            ; so can display dollar    sign
  647.     Cmp    AL,0            ;Ignore    zeros
  648.     Je    PS1
  649.     Mov    DL,AL
  650.     Mov    AH,2            ;Display to standard device
  651.     Int    21h
  652.     Jmp    PS1
  653.  
  654. PS9:    Pop    SI
  655.     Pop    BX
  656.     Ret
  657. PrintS    Endp
  658.  
  659.     Page
  660. ;
  661. ;    Allocate up to 32K per buffer by modifying memory
  662. ;    to use all of the 64K allowed for a COM    program.
  663. ;    This is    more complicated than using data segments
  664. ;    for the    buffers, but has the advantages    of allowing
  665. ;    for variable buffer sizes depending upon the amount
  666. ;    of memory available. It    also allows DS and ES to remain
  667. ;    static.    Besides, the COM version is under 2K bytes.
  668.  
  669. Alloc    Proc    Near            ;Get I/O buffers
  670.     Mov    CX,PgmSize        ;Program size in paragraphs
  671.     Mov    BX,Word    Ptr DS:[2]    ;DOS ending seg    address
  672.     Mov    AX,CS            ;My starting seg address
  673.     Sub    BX,AX            ;Paragraphs for    this COM program
  674.     Sub    BX,CX            ; less code size
  675.     Add    AX,CX            ;Next available    segment    addr
  676.  
  677.     Cmp    BX,Maxcore        ;Can only use 64k
  678.     Jbe    Alloc0
  679.     Mov    BX,Maxcore
  680. Alloc0:    Mov    In_Ptr,AX        ;Seg addr for input buffer
  681.     Cmp    BX,MinCore        ;Enough    just to    run?
  682.     Jb    Alloc1
  683.     Sub    BX,32            ;Size less stack and PSP
  684. Alloc2:    Sar    BX,1            ;Paras for each    buffer
  685.     Add    AX,BX
  686.     Mov    Out_Ptr,AX        ;Seg addr for output buffer
  687.  
  688.     Mov    AX,BX
  689.     Mov    CL,4
  690.     Shl    AX,CL            ;Convert to bytes
  691.     Mov    BufLen,AX
  692.     Mov    Olen,AX
  693.     Cmp    AX,Minpara        ;Have enough?
  694.     Jb    Alloc0            ; nope,    bye
  695.  
  696.     Mov    DX,DS            ;Convert ptrs to offsets
  697.     Mov    AX,In_Ptr
  698.     Sub    AX,DX
  699.     Shl    AX,CL
  700.     Mov    In_Ptr,AX
  701.     Mov    Iptr,AX
  702.  
  703.     Mov    AX,Out_Ptr
  704.     Sub    AX,DX
  705.     Shl    AX,CL
  706.     Mov    Out_Ptr,AX
  707.     Mov    Optr,AX
  708.     Ret
  709.  
  710. Alloc1:    Mov    DX,Offset Msg4a        ;Not enough memory
  711.     Jmp    Error
  712.  
  713. Alloc    Endp
  714.  
  715. Tabs    Endp
  716.  
  717. Rec    Db    0            ;Current record
  718.  
  719. PgmEnd    Equ    $+MaxRec
  720.  
  721. PgmSize    Equ    (PgmEnd-Cseg+256)/16    ;Cseg and stack    length
  722. Maxcore    Equ    4096-PgmSize        ;Max I/O buffer    size, paras
  723. Minpara    Equ    32
  724.  
  725. Cseg    Ends
  726.     End    Tabs
  727.